home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Python / thread_beos.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-03  |  7.7 KB  |  361 lines

  1. /***********************************************************
  2. BeOS thread support by Chris Herborth (chrish@qnx.com)
  3. ******************************************************************/
  4.  
  5. #include <kernel/OS.h>
  6. #include <support/SupportDefs.h>
  7. #include <errno.h>
  8.  
  9. /* ----------------------------------------------------------------------
  10.  * Fast locking mechanism described by Benoit Schillings (benoit@be.com)
  11.  * in the Be Developer's Newsletter, Issue #26 (http://www.be.com/).
  12.  */
  13. typedef struct benaphore {
  14.     sem_id _sem;
  15.     int32  _atom;
  16. } benaphore_t;
  17.  
  18. static status_t benaphore_create( const char *name, benaphore_t *ben );
  19. static status_t benaphore_destroy( benaphore_t *ben );
  20. static status_t benaphore_lock( benaphore_t *ben );
  21. static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros );
  22. static status_t benaphore_unlock( benaphore_t *ben );
  23.  
  24. static status_t benaphore_create( const char *name, benaphore_t *ben )
  25. {
  26.     if( ben != NULL ) {
  27.         ben->_atom = 0;
  28.         ben->_sem = create_sem( 0, name );
  29.         
  30.         if( ben->_sem < B_NO_ERROR ) {
  31.             return B_BAD_SEM_ID;
  32.         }
  33.     } else {
  34.         return EFAULT;
  35.     }
  36.     
  37.     return EOK;
  38. }
  39.  
  40. static status_t benaphore_destroy( benaphore_t *ben )
  41. {
  42.     if( ben->_sem >= B_NO_ERROR ) {
  43.         status_t retval = benaphore_timedlock( ben, 0 );
  44.         
  45.         if( retval == EOK || retval == EWOULDBLOCK ) {
  46.             status_t del_retval = delete_sem( ben->_sem );
  47.             
  48.             return del_retval;
  49.         }
  50.     }
  51.  
  52.     return B_BAD_SEM_ID;
  53. }
  54.  
  55. static status_t benaphore_lock( benaphore_t *ben )
  56. {
  57.     int32 prev = atomic_add( &(ben->_atom), 1 );
  58.     
  59.     if( prev > 0 ) {
  60.         return acquire_sem( ben->_sem );
  61.     }
  62.     
  63.     return EOK;
  64. }
  65.  
  66. static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros )
  67. {
  68.     int32 prev = atomic_add( &(ben->_atom), 1 );
  69.     
  70.     if( prev > 0 ) {
  71.         status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
  72.         
  73.         switch( retval ) {
  74.         case B_WOULD_BLOCK:    /* Fall through... */
  75.         case B_TIMED_OUT:
  76.             return EWOULDBLOCK;
  77.             break;
  78.         case B_OK:
  79.             return EOK;
  80.             break;
  81.         default:
  82.             return retval;
  83.             break;
  84.         }
  85.     }
  86.     
  87.     return EOK;
  88. }
  89.  
  90. static status_t benaphore_unlock( benaphore_t *ben )
  91. {
  92.     int32 prev = atomic_add( &(ben->_atom), -1 );
  93.     
  94.     if( prev > 1 ) {
  95.         return release_sem( ben->_sem );
  96.     }
  97.     
  98.     return EOK;
  99. }
  100.  
  101. /* ----------------------------------------------------------------------
  102.  * Initialization.
  103.  */
  104. static void PyThread__init_thread( void )
  105. {
  106.     /* Do nothing. */
  107.     return;
  108. }
  109.  
  110. /* ----------------------------------------------------------------------
  111.  * Thread support.
  112.  *
  113.  * Only ANSI C, renamed functions here; you can't use K&R on BeOS,
  114.  * and there's no legacy thread module to support.
  115.  */
  116.  
  117. static int32 thread_count = 0;
  118.  
  119. int PyThread_start_new_thread( void (*func)(void *), void *arg )
  120. {
  121.     status_t success = 0;
  122.     thread_id tid;
  123.     char name[B_OS_NAME_LENGTH];
  124.     int32 this_thread;
  125.  
  126.     dprintf(("PyThread_start_new_thread called\n"));
  127.  
  128.     /* We are so very thread-safe... */
  129.     this_thread = atomic_add( &thread_count, 1 );
  130.     sprintf( name, "python thread (%d)", this_thread );
  131.  
  132.     tid = spawn_thread( (thread_func)func, name,
  133.                         B_NORMAL_PRIORITY, arg );
  134.     if( tid > B_NO_ERROR ) {
  135.         success = resume_thread( tid );
  136.     }
  137.  
  138.     return ( success == B_NO_ERROR ? 1 : 0 );
  139. }
  140.  
  141. long PyThread_get_thread_ident( void )
  142. {
  143.     /* Presumed to return the current thread's ID... */
  144.     thread_id tid;
  145.     tid = find_thread( NULL );
  146.     
  147.     return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
  148. }
  149.  
  150. static void do_PyThread_exit_thread( int no_cleanup )
  151. {
  152.     int32 threads;
  153.  
  154.     dprintf(("PyThread_exit_thread called\n"));
  155.  
  156.     /* Thread-safe way to read a variable without a mutex: */
  157.     threads = atomic_add( &thread_count, 0 );
  158.  
  159.     if( threads == 0 ) {
  160.         /* No threads around, so exit main(). */
  161.         if( no_cleanup ) {
  162.             _exit(0);
  163.         } else {
  164.             exit(0);
  165.         }
  166.     } else {
  167.         /* Oh, we're a thread, let's try to exit gracefully... */
  168.         exit_thread( B_NO_ERROR );
  169.     }
  170. }
  171.  
  172. void PyThread_exit_thread( void )
  173. {
  174.     do_PyThread_exit_thread(0);
  175. }
  176.  
  177. void PyThread__exit_thread( void )
  178. {
  179.     do_PyThread_exit_thread(1);
  180. }
  181.  
  182. #ifndef NO_EXIT_PROG
  183. static void do_PyThread_exit_prog( int status, int no_cleanup )
  184. {
  185.     dprintf(("PyThread_exit_prog(%d) called\n", status));
  186.  
  187.     /* No need to do anything, the threads get torn down if main() exits. */
  188.  
  189.     if (no_cleanup) {
  190.         _exit(status);
  191.     } else {
  192.         exit(status);
  193.     }
  194. }
  195.  
  196. void PyThread_exit_prog( int status )
  197. {
  198.     do_PyThread_exit_prog(status, 0);
  199. }
  200.  
  201. void PyThread__exit_prog( int status )
  202. {
  203.     do_PyThread_exit_prog(status, 1);
  204. }
  205. #endif /* NO_EXIT_PROG */
  206.  
  207. /* ----------------------------------------------------------------------
  208.  * Lock support.
  209.  */
  210.  
  211. static int32 lock_count = 0;
  212.  
  213. PyThread_type_lock PyThread_allocate_lock( void )
  214. {
  215.     benaphore_t *lock;
  216.     status_t retval;
  217.     char name[B_OS_NAME_LENGTH];
  218.     int32 this_lock;
  219.     
  220.     dprintf(("PyThread_allocate_lock called\n"));
  221.  
  222.     lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
  223.     if( lock == NULL ) {
  224.         /* TODO: that's bad, raise MemoryError */
  225.         return (PyThread_type_lock)NULL;
  226.     }
  227.  
  228.     this_lock = atomic_add( &lock_count, 1 );
  229.     sprintf( name, "python lock (%d)", this_lock );
  230.  
  231.     retval = benaphore_create( name, lock );
  232.     if( retval != EOK ) {
  233.         /* TODO: that's bad, raise an exception */
  234.         return (PyThread_type_lock)NULL;
  235.     }
  236.  
  237.     dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
  238.     return (PyThread_type_lock) lock;
  239. }
  240.  
  241. void PyThread_free_lock( PyThread_type_lock lock )
  242. {
  243.     status_t retval;
  244.  
  245.     dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
  246.     
  247.     retval = benaphore_destroy( (benaphore_t *)lock );
  248.     if( retval != EOK ) {
  249.         /* TODO: that's bad, raise an exception */
  250.         return;
  251.     }
  252. }
  253.  
  254. int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag )
  255. {
  256.     int success;
  257.     status_t retval;
  258.  
  259.     dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
  260.  
  261.     if( waitflag ) {
  262.         retval = benaphore_lock( (benaphore_t *)lock );
  263.     } else {
  264.         retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
  265.     }
  266.     
  267.     if( retval == EOK ) {
  268.         success = 1;
  269.     } else {
  270.         success = 0;
  271.         
  272.         /* TODO: that's bad, raise an exception */
  273.     }
  274.  
  275.     dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
  276.     return success;
  277. }
  278.  
  279. void PyThread_release_lock( PyThread_type_lock lock )
  280. {
  281.     status_t retval;
  282.     
  283.     dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
  284.     
  285.     retval = benaphore_unlock( (benaphore_t *)lock );
  286.     if( retval != EOK ) {
  287.         /* TODO: that's bad, raise an exception */
  288.         return;
  289.     }
  290. }
  291.  
  292. /* ----------------------------------------------------------------------
  293.  * Semaphore support.
  294.  *
  295.  * Guido says not to implement this because it's not used anywhere;
  296.  * I'll do it anyway, you never know when it might be handy, and it's
  297.  * easy...
  298.  */
  299. PyThread_type_sema PyThread_allocate_sema( int value )
  300. {
  301.     sem_id sema;
  302.     
  303.     dprintf(("PyThread_allocate_sema called\n"));
  304.  
  305.     sema = create_sem( value, "python semaphore" );
  306.     if( sema < B_NO_ERROR ) {
  307.         /* TODO: that's bad, raise an exception */
  308.         return 0;
  309.     }
  310.  
  311.     dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
  312.     return (PyThread_type_sema) sema;
  313. }
  314.  
  315. void PyThread_free_sema( PyThread_type_sema sema )
  316. {
  317.     status_t retval;
  318.     
  319.     dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
  320.     
  321.     retval = delete_sem( (sem_id)sema );
  322.     if( retval != B_NO_ERROR ) {
  323.         /* TODO: that's bad, raise an exception */
  324.         return;
  325.     }
  326. }
  327.  
  328. int PyThread_down_sema( PyThread_type_sema sema, int waitflag )
  329. {
  330.     status_t retval;
  331.  
  332.     dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema, waitflag));
  333.  
  334.     if( waitflag ) {
  335.         retval = acquire_sem( (sem_id)sema );
  336.     } else {
  337.         retval = acquire_sem_etc( (sem_id)sema, 1, B_TIMEOUT, 0 );
  338.     }
  339.     
  340.     if( retval != B_NO_ERROR ) {
  341.         /* TODO: that's bad, raise an exception */
  342.         return 0;
  343.     }
  344.  
  345.     dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
  346.     return -1;
  347. }
  348.  
  349. void PyThread_up_sema( PyThread_type_sema sema )
  350. {
  351.     status_t retval;
  352.     
  353.     dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
  354.     
  355.     retval = release_sem( (sem_id)sema );
  356.     if( retval != B_NO_ERROR ) {
  357.         /* TODO: that's bad, raise an exception */
  358.         return;
  359.     }
  360. }
  361.